﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Clojure;
public class Unit : MonoBehaviour 
{
    public int GamePlayerId;
    public string Id;
    public int MaxHP;
    public int hp;
    public int HP 
    {
        set 
        {
            
            
            this.hp = value;
            if (this.HP <= 0)
            {
                this.IsDie = true;
                this.CallEvent("UnitDie");
            }
            this.CallEvent("HPChange");
        }
        get { return this.hp; }
    }
    public int MaxMP; 
    public int MP;
    public int MoveSpeed;

    public bool IsDie  = false;
    Dictionary<int, Ability> Abilities = new Dictionary<int, Ability>();
    List<Actor> Actors  =  new List<Actor>();
    public List<Weapon> Weapons = new List<Weapon>();

    Dictionary<string, List<Actor>> UnitEventHandlers = new Dictionary<string, List<Actor>>();
    public Clojure.Context Context;
    public List<Mover> Movers = new List<Mover>();
    CommandQueue commandQueue;

    Dictionary<string, bool> flags = new Dictionary<string, bool>();

    /// <summary>
    /// 命令队列
    /// </summary>
    public CommandQueue CmdQueue 
    {
        get 
        {
            if (this.commandQueue == null) 
            {
                this.commandQueue = new CommandQueue();
            }
            return this.commandQueue;
        }
    }

    public enum UnitType 
    {
        Unit,        //普通单位
        MissileUnit, //投射物,抛射物
    }

    public UnitType Type;

    public XmlUnit xmlUnit;
    
    public virtual void Init()
    {
        //Def Clojure
        Context = new Context(RT.MainContext);
        Context.Define("self-unit", new ObjectNode(this));
        this.HP = xmlUnit.HP;
        this.MP = xmlUnit.MP;
        this.MaxHP = xmlUnit.HP;
        this.MaxMP = xmlUnit.MP;
        this.MoveSpeed = xmlUnit.MoveSpeed;
        //Unit Flags
        this.flags = xmlUnit.Flags;
        //Actor
        if(xmlUnit.Actors!=null)
        for (int i = 0; i < xmlUnit.Actors.ChildNodes.Count;i++ )
        {
            string actorName = xmlUnit.Actors.ChildNodes[i].Attributes["Name"].Value;
            Actor newActor = new Actor(this,ActorManager.Instance.Actors[actorName]);
            this.Actors.Add(newActor);
        }
        //Abilities
        if(xmlUnit.Abilities != null)
        for (int i = 0; i < xmlUnit.Abilities.ChildNodes.Count;i++) 
        {
          string abilityName = xmlUnit.Abilities.ChildNodes[i].Name;
          Ability ability = (Ability)this.gameObject.AddComponent(abilityName);
          ability.Init(this);
          this.AddAbility(i,ability);
        }
         
        //Weapons
        if(xmlUnit.Weapons != null)
        for (int i = 0; i < xmlUnit.Weapons.ChildNodes.Count;i++)
        {
            string weaponName = xmlUnit.Weapons.ChildNodes[i].Attributes["Name"].Value;
            GameObject weaponObj = new GameObject(weaponName);
            weaponObj.transform.parent = this.transform;
            weaponObj.transform.localPosition = Vector3.zero;
            weaponObj.transform.localScale = Vector3.one;
            weaponObj.transform.localRotation = Quaternion.identity;
            Weapon weapon = weaponObj.AddComponent<Weapon>();
            weapon.Init(this,WeaponManager.Instance.Weapons[weaponName]);
            this.Weapons.Add(weapon);
        }
        CallEvent("UnitCreate");
    }

    public virtual void OnLoad() 
    {
        this.Type = UnitType.Unit;
        for (int i = 0; i< this.Abilities.Count;i++)
        {
            this.Abilities[i].OnLoad();
        }
    }

    public bool GetFlag(string key)
    {
        if (this.flags.ContainsKey(key)) 
        {
            return this.flags[key];
        } 
        return false;
    }
    public void SetFlag(string k,bool v) 
    {
        this.flags[k] = v;
    }
    public void AddAbility(int id,Ability ability)
    {
        this.Abilities[id] = ability;
    }
    public T GetAbility<T>(int id) where T:Ability
    {
        return (T)this.Abilities[id];
    }

    public void AddMover(Mover mover) 
    {
        this.Movers.Add(mover);
    }

    void Update() 
    {
        if (this.Movers.Count > 0) 
        {
            this.Movers[0].UpdateMove();
        }
    }

    public void AddEventHandler(string strKey, Actor actor) 
    {
        if (!this.UnitEventHandlers.ContainsKey(strKey)) 
        {
            this.UnitEventHandlers[strKey] = new List<Actor>();
        }
        this.UnitEventHandlers[strKey].Add(actor);
    }
 
    public void CallEvent(string eventName) 
    {
        if(this.UnitEventHandlers.ContainsKey(eventName))
        for (int i = 0; i < this.UnitEventHandlers[eventName].Count;i++ ) 
        {
            UnitEventHandlers[eventName][i].CallEvent(eventName);
        }
        GameTrigger.Instance.CallEvent(eventName,this); 
    }

    public float GetAttackRange() 
    {
        return this.Weapons[0].AttackRange;
    }



}
